package com.ruoyi.walmart.service.shipments.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.ruoyi.walmart.domain.shipments.ShipmentMatch;
import com.ruoyi.walmart.domain.shipments.ShipmentStock;
import com.ruoyi.walmart.domain.shipments.dto.CostFreightPair;
import com.ruoyi.walmart.domain.shipments.dto.MatchAggBySku;
import com.ruoyi.walmart.domain.shipments.dto.SkuGtinKey;
import com.ruoyi.walmart.domain.shipments.dto.SkuGtinQty;
import com.ruoyi.walmart.mapper.shipments.ShipmentMatchMapper;
import com.ruoyi.walmart.mapper.shipments.ShipmentStockMapper;
import com.ruoyi.walmart.service.shipments.ShipmentMatchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ShipmentMatchServiceImpl implements ShipmentMatchService {

    @Autowired
    private ShipmentStockMapper shipmentStockMapper;
    @Autowired
    private ShipmentMatchMapper shipmentMatchMapper;

    /**
     * 核心方法：接收 parseDetails 汇总出来的 qtyMap（key =  sku，value = 本次要匹配的数量）
     * 1) 做库存分配、更新 stock、插入 match 记录
     * 2) 同时收集所有用到的 Stock 记录的成本和头程，最后按「记录数」取平均
     * 返回：Map<sku, CostFreightPair>，方便拿去给账单明细 detail.setCost()/setFirstMile()
     */
    @Override
    public Map<SkuGtinKey, CostFreightPair> allocateBillingQtyBySku(List<SkuGtinQty> skuGtinQtyList, Long authId, Long wprId) {

        // 按 SKU 分组，方便后续处理
        Map<String, List<SkuGtinQty>> skuToGtinDetailsMap = skuGtinQtyList.stream()
                .collect(Collectors.groupingBy(SkuGtinQty::getSku));

        List<String> skus = new ArrayList<>(skuToGtinDetailsMap.keySet());

        // 先批量查出每个shipment中SKU的已匹配总量
        List<MatchAggBySku> aggList = shipmentMatchMapper.selectMatchedSumBySkus(skus,authId);

        // 批量把已匹配数量写到 stock 表：matched_qty 设为已匹配，unmatched_qty = received_qty - matched_qty
        for (MatchAggBySku agg : aggList) {
            shipmentStockMapper.update(
                    null,
                    new LambdaUpdateWrapper<ShipmentStock>()
                            .isNotNull(ShipmentStock::getActualDeliveryDate)
                            .setSql("matched_qty   = " + agg.getMatchedQtySum())
                            .setSql("unmatched_qty = qty - approved_qty - " + agg.getMatchedQtySum())
                            .eq(ShipmentStock::getShipmentId, agg.getShipmentId())
                            .eq(ShipmentStock::getSku, agg.getSku())
            );
        }

        // 对每个 SKU 做分配
        for (String sku : skus) {

            // 查找当前 SKU 是否有匹配记录
            Optional<MatchAggBySku> matchingAgg = aggList.stream()
                    .filter(agg -> agg.getSku().equals(sku))
                    .findFirst();

            if (matchingAgg.isPresent()) {
                // 如果有匹配记录，更新 matched_qty 和 unmatched_qty
                MatchAggBySku agg = matchingAgg.get();
                shipmentStockMapper.update(
                        null,
                        new LambdaUpdateWrapper<ShipmentStock>()
                                .isNotNull(ShipmentStock::getActualDeliveryDate)
                                .setSql("matched_qty   = " + agg.getMatchedQtySum())
                                .setSql("unmatched_qty = qty - approved_qty - " + agg.getMatchedQtySum())
                                .eq(ShipmentStock::getShipmentId, agg.getShipmentId())
                                .eq(ShipmentStock::getSku, agg.getSku())
                );
            } else {
                // 只有当 matched_qty 和 unmatched_qty 都为 0 时才更新
                shipmentStockMapper.update(
                        null,
                        new LambdaUpdateWrapper<ShipmentStock>()
                                .isNotNull(ShipmentStock::getActualDeliveryDate)
                                .eq(ShipmentStock::getMatchedQty, 0)
                                .eq(ShipmentStock::getUnmatchedQty, 0)
                                .setSql("unmatched_qty = qty - approved_qty") // 设置 unmatched_qty 为 received_qty
                                .eq(ShipmentStock::getSku, sku)
                                .eq(ShipmentStock::getAuthId, authId) // 确保匹配对应的 authId
                );
            }
            // 🔥 关键修改：获取该SKU下的所有GTIN明细
            List<SkuGtinQty> gtinDetails = skuToGtinDetailsMap.get(sku);
            if (gtinDetails.isEmpty()) {
                continue;
            }

            // 查出所有 ShipmentStock（跨 shipment）及各自历史 matched
            List<ShipmentStock> stocks =  shipmentStockMapper.selectList(new LambdaQueryWrapper<ShipmentStock>()
                            .isNotNull(ShipmentStock::getActualDeliveryDate)
                            .eq(ShipmentStock::getAuthId,authId)
                            .eq(ShipmentStock::getSku,sku)
                            .orderByAsc(ShipmentStock::getActualDeliveryDate)
            );

            // 🔥 关键修改：按GTIN明细分配库存
            allocateStockToGtinDetails(stocks, gtinDetails, wprId, authId, sku);
        }

        // 查询每个 SKU 的加权平均成本和头程费用
        List<CostFreightPair> avgList = shipmentMatchMapper.selectAvgCostFreightBySku(authId, wprId);

        Map<SkuGtinKey, CostFreightPair> result = new HashMap<>();

        for (CostFreightPair agg : avgList) {
            SkuGtinKey key = new SkuGtinKey(agg.getSku(), agg.getGtin());
            result.put(key, agg); // 直接使用查询结果，因为已经包含了SKU和GTIN
        }
        return result;
    }
    /**
     * 将库存分配到不同的GTIN明细上
     */
    private void allocateStockToGtinDetails(
            List<ShipmentStock> stocks,
            List<SkuGtinQty> gtinDetails,  // 这里仍然需要 gtinDetails
            Long wprId,
            Long authId,
            String sku) {

        int stockIndex = 0;

        for (SkuGtinQty gtinDetail : gtinDetails) {
            int remainingQty = gtinDetail.getQty();

            while (remainingQty > 0 && stockIndex < stocks.size()) {
                ShipmentStock currentStock = stocks.get(stockIndex);
                int available = currentStock.getUnmatchedQty();

                if (available <= 0) {
                    stockIndex++;
                    continue;
                }

                int canUse = Math.min(available, remainingQty);

                // 更新库存
                int newUnmatched = available - canUse;
                shipmentStockMapper.update(null, new LambdaUpdateWrapper<ShipmentStock>()
                        .setSql("matched_qty = matched_qty + " + canUse)
                        .setSql("unmatched_qty = " + newUnmatched)
                        .setSql("status = CASE WHEN " + newUnmatched + " = 0 THEN 1 ELSE status END")
                        .eq(ShipmentStock::getId, currentStock.getId())
                );

                // 插入匹配记录
                ShipmentMatch newMatch = new ShipmentMatch();
                newMatch.setId(IdWorker.getId());
                newMatch.setWprId(wprId);
                newMatch.setProductCost(currentStock.getProductCost());
                newMatch.setFirstLeg(currentStock.getFirstLeg());
                newMatch.setShipmentId(currentStock.getShipmentId());
                newMatch.setSku(sku);
                newMatch.setGtin(gtinDetail.getGtin());  // 使用具体的 GTIN
                newMatch.setMatchedQty(canUse);
                newMatch.setMatchedTime(LocalDateTime.now());
                newMatch.setAuthId(authId);
                shipmentMatchMapper.insert(newMatch);

                remainingQty -= canUse;
                currentStock.setUnmatchedQty(newUnmatched);

                if (currentStock.getUnmatchedQty() <= 0) {
                    stockIndex++;
                }
            }

            if (remainingQty > 0) {
//                log.warn("SKU: {}, GTIN: {} 库存不足，剩余未匹配: {}",
//                        sku, gtinDetail.getGtin(), remainingQty);
            }
        }
    }
}
